/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ua.lviv.franko.matrix.hash.gauss;

import java.util.ArrayList;
import java.util.List;

import ua.lviv.franko.matrix.Array;
import ua.lviv.franko.matrix.Hash;
import ua.lviv.franko.matrix.IRow;
import ua.lviv.franko.matrix.RowType;

/**
 * 
 * @author marko
 */
public class HashMatrixGaussStyle extends Matrix {
	private IRow[]		jp, jm;
	private double[]	dd;
	private RowType		type;

	public HashMatrixGaussStyle(RowType type, int N) {
		super(N);
		dd = new double[N];
		this.type = type;
		if (type == RowType.HASH_TYPE) {
			jp = new HashGauss[N];
			jm = new HashGauss[N];
			for (int i = 0; i < N; i++) {
				jp[i] = new HashGauss();
				jm[i] = new HashGauss();
			}
		} else {
			jp = new ArrayGauss[N];
			jm = new ArrayGauss[N];
			for (int i = 0; i < N; i++) {
				jp[i] = new ArrayGauss();
				jm[i] = new ArrayGauss();
			}
		}
	}

	public void setValue(int row, int col, double value) {
		if (row == col) {
			dd[row] = value;
			return;
		}
		int d = getD(row, col);
		int j = getJ(row, col);
		if (j > 0)
			jp[d].setValue(j, value);
		else
			jm[d].setValue(-j, value);
	}

	public void addValue(int row, int col, double value) {
		if (value == 0)
			return;
		if (row == col) {
			dd[row] += value;
			return;
		}
		int d = getD(row, col);
		int j = getJ(row, col);
		if (j > 0)
			jp[d].addValue(j, value);
		else
			jm[d].addValue(-j, value);
	}

	public double getValue(int row, int col) {
		if (row == col)
			return dd[row];
		int d = getD(row, col);
		int j = getJ(row, col);
		return (j > 0) ? jp[d].getValue(j) : jm[d].getValue(-j);
	}

	public void getJRow(int d, int[] indexes, double[] values) {
		jp[d].getValues(indexes, values);
		for (int i = 0; i < indexes.length; i++) {
			indexes[i] = getCol(d, indexes[i]);
		}
	}

	public void getJCol(int d, int[] indexes, double[] values) {
		jm[d].getValues(indexes, values);
		for (int i = 0; i < indexes.length; i++) {
			indexes[i] = getRow(d, -indexes[i]);
		}

	}

	public void getJCol(int d, List<Integer> indexes, List<Double> values) {
		indexes = jm[d].getIndexes();
		values = jm[d].getValues();
		for (int i = 0; i < indexes.size(); i++) {
			indexes.set(i, getRow(d, -indexes.get(i)));
		}
	}

	public List<Integer> getJColIndex(int d) {
		List<Integer> indexes = jm[d].getIndexes();
		for (int i = 0; i < indexes.size(); i++) {
			indexes.set(i, getRow(d, -indexes.get(i)));
		}
		return indexes;
	}

	public List<Double> getJColValues(int d) {
		return new ArrayList<Double>(jm[d].getValues());
	}

	public List<Integer> getJRowIndex(int d) {
		List<Integer> indexes = jp[d].getIndexes();
		for (int i = 0; i < indexes.size(); i++) {
			indexes.set(i, getCol(d, indexes.get(i)));
		}
		return indexes;
	}

	public List<Double> getJRowValues(int d) {
		return new ArrayList<Double>(jp[d].getValues());
	}

}
